import java.util.Scanner;
public class SDES {
	static int[] key1=new int[8];
	static int[] key2=new int[8];
	static int[] IP=new int[8];
	static int[] EP=new int[8];
	static int[] P4=new int[4];
	public static void main(String args[])
	{
		int i=0;
		int[] ptext=new int[8];
		int[] ctext=new int[8];
		int[] key=new int[10];
		int[] p10=new int[10];
		int[] p8=new int[10];
		
		Scanner sc=new Scanner(System.in);
		
		System.out.println("Enter the Plaintext");
		for(i=0;i<8;i++)
			ptext[i]=sc.nextInt();
		
		System.out.println("Enter the Key");
		for(i=0;i<10;i++)
			key[i]=sc.nextInt();
		
		System.out.println("Enter P10");
		for(i=0;i<10;i++)
			p10[i]=sc.nextInt();
		
		
		System.out.println("Enter P8");
		for(i=0;i<8;i++)
			p8[i]=sc.nextInt();
		
		makeKeys(p8,p10,key,ptext);
		ctext=encrypt(key,ptext);
		decrypt(key,ctext);
	}
	
	static void makeKeys(int[] p8,int[] p10,int[] key,int[] ptext)
	{
		int[] key_p10=new int[10];
		int temp1=0,temp2=0,i=0;
		//Apply p10 on the key[] array
		for(i=0;i<10;i++)
		{
			key_p10[i]=key[p10[i]-1];
		}
		//After applying p10, the key becomes:
		System.out.print("After applying p10, the key is ");
		for(i=0;i<10;i++)
		{
			System.out.print(key_p10[i]+" ");
		}
		
		//Apply LS1
		temp1=key_p10[0];
		for(i=0;i<4;i++)
		{
			key_p10[i]=key_p10[i+1];
		}
		key_p10[i]=temp1;
		
		temp1=key_p10[key_p10.length/2];
		for(i=key_p10.length/2;i<key_p10.length-1;i++)
		{
			key_p10[i]=key_p10[i+1];
		}
		key_p10[i]=temp1;
		
		System.out.print("\nAfter LS1, the key is ");
		for(i=0;i<10;i++)
		{
			System.out.print(key_p10[i]+" ");
		}
		//End of LS1
		
		//Applying P8
		for(i=0;i<8;i++)
		{
			key1[i]=key_p10[p8[i]-1];
		}
		
		System.out.print("\nKey1 is ");
		for(i=0;i<8;i++)
		{
			System.out.print(key1[i]+" ");
		}
		//End of P8
		
		//Apply LS2
		temp1=key_p10[0];
		temp2=key_p10[1];
		for(i=0;i<3;i++)
		{
			key_p10[i]=key_p10[i+2];
		}
		key_p10[i]=temp1;
		key_p10[i+1]=temp2;
		
		temp1=key_p10[key_p10.length/2];
		temp2=key_p10[(key_p10.length/2)+1];
		for(i=key_p10.length/2;i<key_p10.length-2;i++)
		{
			key_p10[i]=key_p10[i+2];
		}
		key_p10[i]=temp1;
		key_p10[i+1]=temp2;
		
		System.out.print("\nAfter LS2, the key is ");
		for(i=0;i<10;i++)
		{
			System.out.print(key_p10[i]+" ");
		}
		//End of LS2
		
		//Applying P8
		for(i=0;i<8;i++)
		{
			key2[i]=key_p10[p8[i]-1];
		}
		
		System.out.print("\nKey2 is ");
		for(i=0;i<8;i++)
		{
			System.out.print(key2[i]+" ");
		}
		//End of P8
		
	}
static int[] encrypt(int[] key,int[] ptext) {
		
		Scanner sc=new Scanner(System.in);
		int i=0,r1=0,c1=0,r2=0,c2=0,s0_val=0,s1_val=0,temp=0;
		int[] ptext_ip=new int[8];
		int[] ptext_ep=new int[8];
		int[] sbox=new int[8];
		int[] sbox4bits=new int[4];
		int[] sbox4bits_p4=new int[4];
		int[] ptext_p4=new int[8];
		int[] sbox_p4=new int[8];
		int[] sbox_p4_bits=new int[8];
		int[] IP_Inverse=new int[8];
		int[] ctext=new int[8];
		int[] sbox4bits_p4_ep=new int[4];
		int[][] s0={
				{1,0,3,2},
				{3,2,1,0},
				{0,2,3,1},
				{3,1,3,2}
		};
		int[][] s1={
				{0,1,2,3},
				{2,0,1,3},
				{3,0,1,0},
				{2,1,0,3}
		};
		
		System.out.println("\nEnter Initial Permutation");
		for(i=0;i<8;i++)
			IP[i]=sc.nextInt();
		
		//Applying IP on PTEXT
		for(i=0;i<8;i++)
		ptext_ip[i]=ptext[IP[i]-1];
		
		//Hence ptext becomes:
		System.out.print("\nptext after IP is ");
		for(i=0;i<8;i++)
		{
			System.out.print(ptext_ip[i]+" ");
		}
		
		//Take Expansion permutation from user
		System.out.println("Enter Expansion Permutation");
		for(i=0;i<8;i++)
			EP[i]=sc.nextInt();
		
		//Applying EP on PTEXT
		for(i=0;i<8;i++)
			ptext_ep[i]=ptext_ip[EP[i]+4-1];
		
		//After EP
		System.out.print("\nptext after EP is ");
		for(i=0;i<8;i++)
		{
			System.out.print(ptext_ep[i]+" ");
		}
		
		//S-BOX
		for(i=0;i<8;i++)
			sbox[i]=ptext_ep[i]^key1[i];
		
		//The new value
		System.out.print("\nSbox value is ");
		for(i=0;i<8;i++)
		{
			System.out.print(sbox[i]+" ");
		}
		r1=sbox[0]*2+sbox[3];
		c1=sbox[1]*2+sbox[2];
		r2=sbox[4]*2+sbox[7];
		c2=sbox[5]*2+sbox[6];
		
		//print sbox
		System.out.println("\nSbox values are ");
		System.out.println("r1= "+r1+"  c1="+c1+"  r2="+r2+"  c2="+c2);
		
	
		s0_val=s0[r1][c1];
		s1_val=s1[r2][c2];
		System.out.println("s0_val= "+s0_val+"  s1_val="+s1_val);
		i=0;
		if(s0_val==0)
		{
			sbox4bits[0]=0;
			sbox4bits[1]=0;
		}
		else if(s0_val==1)
		{
			sbox4bits[0]=0;
			sbox4bits[1]=1;
		}
		else if(s0_val==2)
		{
			sbox4bits[0]=1;
			sbox4bits[1]=0;
		}
		else if(s0_val==3)
		{
			sbox4bits[0]=1;
			sbox4bits[1]=1;
		}
		
		//For s1 
		if(s1_val==0)
		{
			sbox4bits[2]=0;
			sbox4bits[3]=0;
		}
		else if(s1_val==1)
		{
			sbox4bits[2]=0;
			sbox4bits[1]=1;
		}
		else if(s1_val==2)
		{
			sbox4bits[2]=1;
			sbox4bits[1]=0;
		}
		else if(s1_val==3)
		{
			sbox4bits[2]=1;
			sbox4bits[3]=1;
		}
		System.out.println("\nResulting 4 bits are ");
		for(i=0;i<4;i++)
		{
			System.out.print(sbox4bits[i]+" ");
		}
		
		//Take P4 from user
		System.out.println("Enter P4");
		for(i=0;i<4;i++)
			P4[i]=sc.nextInt();
		
		//Apply P4
		for(i=0;i<4;i++)
		sbox4bits_p4[i]=sbox4bits[P4[i]-1];
		/*System.out.println("\nResulting 4 bits after applying P4 are ");
		for(i=0;i<4;i++)
		{
			System.out.print(sbox4bits_p4[i]+" ");
		}*/
		
		for(i=0;i<8;i++)
		{
			if(i<4)
			{
				ptext_p4[i]=sbox4bits_p4[i]^ptext_ip[i];
			}
			else
			{
				ptext_p4[i]=ptext_ip[i];
			}
		}
		
		System.out.println("\nP4rd array is: ");
		for(i=0;i<8;i++)
		{
			System.out.print(ptext_p4[i]+" ");
		}
		//Swap the nibbles
		for(i=0;i<4;i++)
		{
			temp=ptext_p4[i];
			ptext_p4[i]=ptext_p4[i+4];
			ptext_p4[i+4]=temp;
		}
		System.out.println("\nThe swapped array is: ");
		for(i=0;i<8;i++)
		{
			System.out.print(ptext_p4[i]+" ");
		}
		
		//Applying EP on PTEXT
		for(i=0;i<8;i++)
			ptext_ep[i]=ptext_p4[EP[i]+4-1];
		
		//After EP
		System.out.print("\nptext after EP is ");
		for(i=0;i<8;i++)
		{
			System.out.print(ptext_ep[i]+" ");
		}
		
		//SBOX 2
		//S-BOX
		for(i=0;i<8;i++)
			sbox_p4[i]=ptext_ep[i]^key2[i];
		
		//The new value
		System.out.print("\nSbox value is ");
		for(i=0;i<8;i++)
		{
			System.out.print(sbox_p4[i]+" ");
		}
		r1=sbox_p4[0]*2+sbox_p4[3];
		c1=sbox_p4[1]*2+sbox_p4[2];
		r2=sbox_p4[4]*2+sbox_p4[7];
		c2=sbox_p4[5]*2+sbox_p4[6];
		
		
		//----------------------
		System.out.println("\nSbox values are ");
		System.out.println("r1= "+r1+"  c1="+c1+"  r2="+r2+"  c2="+c2);
		
	
		s0_val=s0[r1][c1];
		s1_val=s1[r2][c2];
		System.out.println("s0_val= "+s0_val+"  s1_val="+s1_val);
		i=0;
		
		for(i=0;i<4;i++)
			sbox4bits[i]=0;
		
		if(s0_val==0)
		{
			sbox4bits[0]=0;
			sbox4bits[1]=0;
		}
		else if(s0_val==1)
		{
			sbox4bits[0]=0;
			sbox4bits[1]=1;
		}
		else if(s0_val==2)
		{
			sbox4bits[0]=1;
			sbox4bits[1]=0;
		}
		else if(s0_val==3)
		{
			sbox4bits[0]=1;
			sbox4bits[1]=1;
		}
		
		//For s1 
		if(s1_val==0)
		{
			sbox4bits[2]=0;
			sbox4bits[3]=0;
		}
		else if(s1_val==1)
		{
			sbox4bits[2]=0;
			sbox4bits[1]=1;
		}
		else if(s1_val==2)
		{
			sbox4bits[2]=1;
			sbox4bits[1]=0;
		}
		else if(s1_val==3)
		{
			sbox4bits[2]=1;
			sbox4bits[3]=1;
		}
		/*DON'T DELETE
		 * while(s0_val > 0){
            sbox4bits[i++] = s0_val%2;
            s0_val = s0_val/2;
        }
		if(i==1)
		{
			temp=sbox4bits[0];
			sbox4bits[0]=sbox4bits[1];
			sbox4bits[1]=temp;
			i++;
		}
		while(s1_val > 0){
            sbox4bits[i++] = s1_val%2;
            s1_val = s1_val/2;
        }
		if(i==2)
		{
			temp=sbox4bits[2];
			sbox4bits[2]=sbox4bits[3];
			sbox4bits[3]=temp;
			i++;
		}*/
		System.out.println("\nResulting 4 bits are ");
		for(i=0;i<4;i++)
		{
			System.out.print(sbox4bits[i]+" ");
		}
	
		//XOR 4 bits of sbox4bits and 4 bits of plaintext_ip
		
		//Applying EP on sbox4bits_p4
		for(i=0;i<4;i++)
			sbox4bits_p4_ep[i]=sbox4bits[P4[i]-1];
		
		for(i=0;i<8;i++)
		{
			if(i<4)
				sbox_p4_bits[i]=sbox4bits_p4_ep[i]^ptext_p4[i];
			else
				sbox_p4_bits[i]=ptext_p4[i];
		}
		
		System.out.println("\nResulting 8 bits are ");
		for(i=0;i<8;i++)
		{
			System.out.print(sbox_p4_bits[i]+" ");
		}
		System.out.println("\nEnter IP Inverse");
		for(i=0;i<8;i++)
			IP_Inverse[i]=sc.nextInt();
		
		for(i=0;i<8;i++)
			ctext[i]=sbox_p4_bits[IP_Inverse[i]-1];
		
		System.out.println("IP_Inverse is ");
		for(i=0;i<8;i++)
		{
			System.out.print(IP_Inverse[i]+" ");
		}
		
		
		System.out.println("\nCiphertext is ");
		for(i=0;i<8;i++)
		{
			System.out.print(ctext[i]+" ");
		}
		return ctext;
	}

static void decrypt(int[] key,int[] ctext) {
	
	Scanner sc=new Scanner(System.in);
	int i=0,r1=0,c1=0,r2=0,c2=0,s0_val=0,s1_val=0,temp=0;
	int[] ctext_ip=new int[8];
	int[] ctext_ep=new int[8];
	int[] sbox=new int[8];
	int[] sbox4bits=new int[4];
	int[] sbox4bits_p4=new int[4];
	int[] ctext_p4=new int[8];
	int[] sbox_p4=new int[8];
	int[] sbox_p4_bits=new int[8];
	int[] IP_Inverse=new int[8];
	int[] ptext=new int[8];
	int[] sbox4bits_p4_ep=new int[4];
	int[][] s0={
			{1,0,3,2},
			{3,2,1,0},
			{0,2,3,1},
			{3,1,3,2}
	};
	int[][] s1={
			{0,1,2,3},
			{2,0,1,3},
			{3,0,1,0},
			{2,1,0,3}
	};
	
	System.out.println("\nEnter Initial Permutation");
	for(i=0;i<8;i++)
		IP[i]=sc.nextInt();
	
	//Applying IP on ctext
	for(i=0;i<8;i++)
	ctext_ip[i]=ctext[IP[i]-1];
	
	//Hence ctext becomes:
	System.out.print("\nctext after IP is ");
	for(i=0;i<8;i++)
	{
		System.out.print(ctext_ip[i]+" ");
	}
	
	//Take Expansion permutation from user
	System.out.println("Enter Expansion Permutation");
	for(i=0;i<8;i++)
		EP[i]=sc.nextInt();
	
	//Applying EP on ctext
	for(i=0;i<8;i++)
		ctext_ep[i]=ctext_ip[EP[i]+4-1];
	
	//After EP
	System.out.print("\nctext after EP is ");
	for(i=0;i<8;i++)
	{
		System.out.print(ctext_ep[i]+" ");
	}
	
	//S-BOX
	for(i=0;i<8;i++)
		sbox[i]=ctext_ep[i]^key2[i];
	
	//The new value
	System.out.print("\nSbox value is ");
	for(i=0;i<8;i++)
	{
		System.out.print(sbox[i]+" ");
	}
	r1=sbox[0]*2+sbox[3];
	c1=sbox[1]*2+sbox[2];
	r2=sbox[4]*2+sbox[7];
	c2=sbox[5]*2+sbox[6];
	//print sbox
	System.out.println("\nSbox values are ");
	System.out.println("r1= "+r1+"  c1="+c1+"  r2="+r2+"  c2="+c2);
	

	s0_val=s0[r1][c1];
	s1_val=s1[r2][c2];
	System.out.println("s0_val= "+s0_val+"  s1_val="+s1_val);
	i=0;
	if(s0_val==0)
	{
		sbox4bits[0]=0;
		sbox4bits[1]=0;
	}
	else if(s0_val==1)
	{
		sbox4bits[0]=0;
		sbox4bits[1]=1;
	}
	else if(s0_val==2)
	{
		sbox4bits[0]=1;
		sbox4bits[1]=0;
	}
	else if(s0_val==3)
	{
		sbox4bits[0]=1;
		sbox4bits[1]=1;
	}
	
	//For s1 
	if(s1_val==0)
	{
		sbox4bits[2]=0;
		sbox4bits[3]=0;
	}
	else if(s1_val==1)
	{
		sbox4bits[2]=0;
		sbox4bits[1]=1;
	}
	else if(s1_val==2)
	{
		sbox4bits[2]=1;
		sbox4bits[1]=0;
	}
	else if(s1_val==3)
	{
		sbox4bits[2]=1;
		sbox4bits[3]=1;
	}
	System.out.println("\nResulting 4 bits are ");
	for(i=0;i<4;i++)
	{
		System.out.print(sbox4bits[i]+" ");
	}
	
	//Take P4 from user
	System.out.println("Enter P4");
	for(i=0;i<4;i++)
		P4[i]=sc.nextInt();
	
	//Apply P4
	for(i=0;i<4;i++)
	sbox4bits_p4[i]=sbox4bits[P4[i]-1];
	/*System.out.println("\nResulting 4 bits after applying P4 are ");
	for(i=0;i<4;i++)
	{
		System.out.print(sbox4bits_p4[i]+" ");
	}*/
	for(i=0;i<8;i++)
	{
		if(i<4)
		{
			ctext_p4[i]=sbox4bits_p4[i]^ctext_ip[i];
		}
		else
		{
			ctext_p4[i]=ctext_ip[i];
		}
	}
	
	System.out.println("\nP4rd array is: ");
	for(i=0;i<8;i++)
	{
		System.out.print(ctext_p4[i]+" ");
	}
	//Swap the nibbles
	for(i=0;i<4;i++)
	{
		temp=ctext_p4[i];
		ctext_p4[i]=ctext_p4[i+4];
		ctext_p4[i+4]=temp;
	}
	System.out.println("\nThe swapped array is: ");
	for(i=0;i<8;i++)
	{
		System.out.print(ctext_p4[i]+" ");
	}
	
	//Applying EP on ctext
	for(i=0;i<8;i++)
		ctext_ep[i]=ctext_p4[EP[i]+4-1];
	
	//After EP
	System.out.print("\nctext after EP is ");
	for(i=0;i<8;i++)
	{
		System.out.print(ctext_ep[i]+" ");
	}
	
	//SBOX 2
	//S-BOX
	for(i=0;i<8;i++)
		sbox_p4[i]=ctext_ep[i]^key1[i];
	
	//The new value
	System.out.print("\nSbox value is ");
	for(i=0;i<8;i++)
	{
		System.out.print(sbox_p4[i]+" ");
	}
	r1=sbox_p4[0]*2+sbox_p4[3];
	c1=sbox_p4[1]*2+sbox_p4[2];
	r2=sbox_p4[4]*2+sbox_p4[7];
	c2=sbox_p4[5]*2+sbox_p4[6];
	
	
	//----------------------
	System.out.println("\nSbox values are ");
	System.out.println("r1= "+r1+"  c1="+c1+"  r2="+r2+"  c2="+c2);
	

	s0_val=s0[r1][c1];
	s1_val=s1[r2][c2];
	System.out.println("s0_val= "+s0_val+"  s1_val="+s1_val);
	i=0;
	
	for(i=0;i<4;i++)
		sbox4bits[i]=0;
	
	if(s0_val==0)
	{
		sbox4bits[0]=0;
		sbox4bits[1]=0;
	}
	else if(s0_val==1)
	{
		sbox4bits[0]=0;
		sbox4bits[1]=1;
	}
	else if(s0_val==2)
	{
		sbox4bits[0]=1;
		sbox4bits[1]=0;
	}
	else if(s0_val==3)
	{
		sbox4bits[0]=1;
		sbox4bits[1]=1;
	}
	
	//For s1 
	if(s1_val==0)
	{
		sbox4bits[2]=0;
		sbox4bits[3]=0;
	}
	else if(s1_val==1)
	{
		sbox4bits[2]=0;
		sbox4bits[1]=1;
	}
	else if(s1_val==2)
	{
		sbox4bits[2]=1;
		sbox4bits[1]=0;
	}
	else if(s1_val==3)
	{
		sbox4bits[2]=1;
		sbox4bits[3]=1;
	}
	/*DON'T DELETE
	 * while(s0_val > 0){
        sbox4bits[i++] = s0_val%2;
        s0_val = s0_val/2;
    }
	if(i==1)
	{
		temp=sbox4bits[0];
		sbox4bits[0]=sbox4bits[1];
		sbox4bits[1]=temp;
		i++;
	}
	while(s1_val > 0){
        sbox4bits[i++] = s1_val%2;
        s1_val = s1_val/2;
    }
	if(i==2)
	{
		temp=sbox4bits[2];
		sbox4bits[2]=sbox4bits[3];
		sbox4bits[3]=temp;
		i++;
	}*/
	System.out.println("\nResulting 4 bits are ");
	for(i=0;i<4;i++)
	{
		System.out.print(sbox4bits[i]+" ");
	}

	//XOR 4 bits of sbox4bits and 4 bits of plaintext_ip
	
	for(i=0;i<4;i++)
		sbox4bits_p4_ep[i]=sbox4bits[P4[i]-1];
	
	for(i=0;i<8;i++)
	{
		if(i<4)
			sbox_p4_bits[i]=sbox4bits_p4_ep[i]^ctext_p4[i];
		else
			sbox_p4_bits[i]=ctext_p4[i];
	}
	
	System.out.println("\nResulting 8 bits are ");
	for(i=0;i<8;i++)
	{
		System.out.print(sbox_p4_bits[i]+" ");
	}
	System.out.println("\nEnter IP Inverse");
	for(i=0;i<8;i++)
		IP_Inverse[i]=sc.nextInt();
	
	for(i=0;i<8;i++)
		ptext[i]=sbox_p4_bits[IP_Inverse[i]-1];
	
	System.out.println("IP_Inverse is ");
	for(i=0;i<8;i++)
	{
		System.out.print(IP_Inverse[i]+" ");
	}
	
	
	System.out.println("\nPlaintext is ");
	for(i=0;i<8;i++)
	{
		System.out.print(ptext[i]+" ");
	}
}


}
/*
Enter the Plaintext
1 0 1 0 0 1 0 1
Enter the Key
0 0 1 0 0 1 0 1 1 1
Enter P10
3 5 2 7 4 10 1 9 8 6
Enter P8
6 3 7 4 8 5 10 9
After applying p10, the key is 1 0 0 0 0 1 0 1 1 1 
After LS1, the key is 0 0 0 0 1 0 1 1 1 1 
Key1 is 0 0 1 0 1 1 1 1 
After LS2, the key is 0 0 1 0 0 1 1 1 0 1 
Key2 is 1 1 1 0 1 0 1 0 
Enter Initial Permutation
2 6 3 1 4 8 5 7

ptext after IP is 0 1 1 1 0 1 0 0 Enter Expansion Permutation
4 1 2 3 2 3 4 1

ptext after EP is 0 0 1 0 1 0 0 0 
Sbox value is 0 0 0 0 0 1 1 1 
Sbox values are 
r1= 0  c1=0  r2=1  c2=3
s0_val= 1  s1_val=3

Resulting 4 bits are 
0 1 1 1 Enter P4
2 4 3 1

P4rd array is: 
1 0 0 1 0 1 0 0 
The swapped array is: 
0 1 0 0 1 0 0 1 
ptext after EP is 1 1 0 0 0 0 1 1 
Sbox value is 0 0 1 0 1 0 0 1 
Sbox values are 
r1= 0  c1=1  r2=3  c2=0
s0_val= 0  s1_val=2

Resulting 4 bits are 
0 0 1 0 
Resulting 8 bits are 
0 1 1 0 1 0 0 1 
Enter IP Inverse
4 1 3 5 7 2 8 6
IP_Inverse is 
4 1 3 5 7 2 8 6 
Ciphertext is 
0 0 1 1 0 1 1 0 
Enter Initial Permutation
2 6 3 1 4 8 5 7

ctext after IP is 0 1 1 0 1 0 0 1 Enter Expansion Permutation
4 1 2 3 2 3 4 1

ctext after EP is 1 1 0 0 0 0 1 1 
Sbox value is 0 0 1 0 1 0 0 1 
Sbox values are 
r1= 0  c1=1  r2=3  c2=0
s0_val= 0  s1_val=2

Resulting 4 bits are 
0 0 1 0 Enter P4
2 4 3 1

P4rd array is: 
0 1 0 0 1 0 0 1 
The swapped array is: 
1 0 0 1 0 1 0 0 
ctext after EP is 0 0 1 0 1 0 0 0 
Sbox value is 0 0 0 0 0 1 1 1 
Sbox values are 
r1= 0  c1=0  r2=1  c2=3
s0_val= 1  s1_val=3

Resulting 4 bits are 
0 1 1 1 
Resulting 8 bits are 
0 1 1 1 0 1 0 0 
Enter IP Inverse
4 1 3 5 7 2 8 6
IP_Inverse is 
4 1 3 5 7 2 8 6 
Plaintext is 
1 0 1 0 0 1 0 1 
*/